package top.songxs.gmall.cart.service.impl;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import top.songxs.gmall.cart.entity.CartItem;
import top.songxs.gmall.cart.service.CartService;
import top.songxs.gmall.cart.vo.UserAuthInfoVo;
import top.songxs.gmall.common.result.Result;
import top.songxs.gmall.common.util.UserAuthUtil;
import top.songxs.gmall.feign.product.SkuInfoFeignClient;
import top.songxs.gmall.product.entity.SkuInfo;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private SkuInfoFeignClient skuInfoFeignClient;

    @Override
    public List<CartItem> cartList() {
        UserAuthInfoVo userAuthInfo = UserAuthUtil.getUserAuthInfo();
        String redisTempKey = "cart:info:" + userAuthInfo.getUserTempId();
        String allwaysKey = "cart:info:" + userAuthInfo.getUserId();

        if (!StringUtils.isEmpty(userAuthInfo.getUserId())) {
            //用户登录了完成购物车数据的合并，只需要将我们用户的临时购物车数据合并
            //获取用户的临时购物车数据
            List<Object> values = redisTemplate.opsForHash().values(redisTempKey);
            values.stream().forEach(obj -> {
                String json = obj.toString();
                CartItem cartItem = JSON.parseObject(json, CartItem.class);
                Long skuId = cartItem.getSkuId();
                Boolean aBoolean = redisTemplate.opsForHash().hasKey(allwaysKey, String.valueOf(skuId));
                //查看用户的购物车中是否有临时购物车中的商品如果有合并时，就把临时购物车的数量加到用户的购物车中
                if (aBoolean) {
                    String userJSONData = redisTemplate.opsForHash().get(allwaysKey, String.valueOf(skuId)).toString();
                    CartItem userCartItem = JSON.parseObject(userJSONData, CartItem.class);
                    userCartItem.setSkuNum(userCartItem.getSkuNum() + cartItem.getSkuNum());
                    redisTemplate.opsForHash().put(allwaysKey, String.valueOf(skuId), JSON.toJSONString(userCartItem));
                } else {
                    //查看用户的购物车中没有临时购物车里面的商品，就把临时购物车里面的商品加入到用户购物车中
                    redisTemplate.opsForHash().put(allwaysKey, String.valueOf(skuId), JSON.toJSONString(cartItem));
                }
            });
            //删除临时购物车
            redisTemplate.delete(redisTempKey);
            //拿到用户购物车中的所有商品信息
            List<Object> userCartList = redisTemplate.opsForHash().values(allwaysKey);
            List<CartItem> cartItemList = userCartList.stream().map(obj -> {
                        String itemJson = obj.toString();
                        CartItem cartItem = JSON.parseObject(itemJson, CartItem.class);
                        updateCartItemPrice(cartItem, allwaysKey);
                        return cartItem;
                    }).sorted((c1, c2) -> (int) (c1.getCreateTime().getTime() - c2.getCreateTime().getTime()))
                    .collect(Collectors.toList());
            if (cartItemList.size() > 3) {
                cartItemList = cartItemList.subList(0, 3);
            }
            return cartItemList;

        } else {
            //用户没有进行登录
            //用户没有进行登录直接查询临时购物车就行了
            Long ttl = redisTemplate.getExpire(redisTempKey);
            if (ttl < 0) {
                redisTemplate.expire(redisTempKey, 30, TimeUnit.DAYS);
            }
            List<Object> values = redisTemplate.opsForHash().values(redisTempKey);
            List<CartItem> cartItemList = values.stream().map(obj -> {
                        String itemJson = obj.toString();
                        CartItem cartItem = JSON.parseObject(itemJson, CartItem.class);
                        this.updateCartItemPrice(cartItem, redisTempKey);
                        return cartItem;
                    }).sorted((c1, c2) -> (int) (c1.getCreateTime().getTime() - c2.getCreateTime().getTime()))
                    .collect(Collectors.toList());
            return cartItemList;
        }
    }

    private void updateCartItemPrice(CartItem cartItem, String allwaysKey) {
        Result<SkuInfo> result = skuInfoFeignClient.getSkuInfo(cartItem.getSkuId());
        SkuInfo skuInfo = result.getData();
        cartItem.setSkuPrice(skuInfo.getPrice());
        //更新redis的价格
        redisTemplate.opsForHash().put(allwaysKey, String.valueOf(skuInfo.getId()), JSON.toJSONString(cartItem));
    }

    @Override
    public void updateCartItem(Long skuId, Integer skuNum) {
        //构建redis key
        String key = this.buildRedisCartKey();
        //从redis中根据购物项
        String Json = (String) redisTemplate.opsForHash().get(key, String.valueOf(skuId));
        CartItem cartItem = JSON.parseObject(Json, CartItem.class);
        //对 redis中的数据进行累加
        int count = cartItem.getSkuNum() + skuNum;
        //对单个商品的数量进行限制，最多单个商品只能添加十个到购物车
        if (count > 10) {
            return;
        }
        cartItem.setSkuNum(count);
        //把最新的数据存入到redis中
        redisTemplate.opsForHash().put(key, String.valueOf(skuId), JSON.toJSONString(cartItem));

    }

    @Override
    public void checkCart(Long skuId, Integer ischecked) {
        String key = this.buildRedisCartKey();
        //从redis中根据购物项
        String Json = (String) redisTemplate.opsForHash().get(key, String.valueOf(skuId));

        CartItem cartItem = JSON.parseObject(Json, CartItem.class);

        //更改isChecked字段
        cartItem.setIsChecked(ischecked);

        //把最新的数据存入到redis中
        redisTemplate.opsForHash().put(key, String.valueOf(skuId), JSON.toJSONString(cartItem));

    }

    @Override
    public void deleteCartItem(Long skuId) {
        String key = this.buildRedisCartKey();
        redisTemplate.opsForHash().delete(key, String.valueOf(skuId));
    }

    private String buildRedisCartKey() {

        UserAuthInfoVo userAuthInfo = UserAuthUtil.getUserAuthInfo();
        String userId = userAuthInfo.getUserId();
        if (!StringUtils.isEmpty(userId)) {
            return "cart:info:" + userId;
        } else {
            return "cart:info:" + userAuthInfo.getUserTempId();
        }

    }
}
